home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr22 / byte24.zip / BENCHCOD.C < prev    next >
Text File  |  1993-04-14  |  41KB  |  1,587 lines

  1. /*«PL1»*/
  2. /*
  3. ** Low-level Benchmarks for 80x86 machines.
  4. ** BYTE Magazine
  5. ** Apr. 1990
  6. **
  7. ** This module contains the high level source for the BYTE benchmarks
  8. ** Routines called from this module may be found in BENCHSUBS.ASM.
  9. **
  10. ** VERSION 2.3 -- This code corrected so that iteration counts are
  11. **  now long integers. -- RG
  12. **
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <stdarg.h>
  17. #include <dos.h>
  18. #include <mem.h>
  19. #include <math.h>
  20. #include <float.h>
  21. #include "benchdef.h"
  22. #include "win.h"
  23.  
  24. /* Typedefs */
  25. typedef struct {
  26.     unsigned int maxhead;    /* Max head number */
  27.     unsigned int maxcyl;    /* Max cylinder number */
  28.     unsigned int sectspertrack;    /* Sectors per track */
  29. } harddiskspecs;
  30.  
  31. /* external globals */
  32. extern unsigned long ll_filelen();
  33. extern volatile struct mcfig machine_config;
  34. extern int tdef[14];
  35. extern int oldlen;
  36.  
  37. /* window prototypes  (winsubs.asm)*/
  38. extern int chattr (win_handle *, int, int, int, int, int, int);
  39. extern int winputch (win_handle *, int, int, char);
  40. extern void clearscreen (void);
  41.  
  42. /* misc prototypes (miscsubs.asm) */
  43. extern void click(void);
  44.  
  45. /*local prototypes */
  46. char *gfname(int);
  47. long randwc(long);
  48. long randnum(long);
  49. double timetodouble( unsigned int *);
  50. void adjust_bar(win_handle*, int, int);
  51.  
  52. /****************************
  53. *          sieve            *
  54. *****************************
  55. ** The (in)famous sieve of Eratosthenes.
  56. ** Call with:
  57. **  sieve (winptr,dotime,acttime,iters)
  58. ** Where:
  59. **  winptr= handle of window upon which to draw slidey-bar; null means don't
  60. **  dotime = # of seconds for the system to execute the sieve
  61. ** Returns:
  62. **  acttime[3] = pointer to a 3-element array
  63. **               acttime[0] = # of microseconds actually elapsed
  64. **               acttime[1] = # of milliseconds actually elapsed
  65. **               acttime[2] = # of seconds actually elapsed
  66. **  iters = number of iterations performed in acttime
  67. */
  68. sieve(winptr,dotime,acttime,iters)
  69. win_handle *winptr;        /* current window */
  70. unsigned int dotime;        /* Seconds to execute */
  71. unsigned int acttime[3];    /* Actual elapsed time */
  72. unsigned long *iters;        /* # of iterations performed */
  73. {
  74. unsigned int mysegptr;        /* Place to hold pointer for segment */
  75. unsigned int mytime[3];        /* Local for time accumulation */
  76.  
  77. /* Clear # of iterations and actual time */
  78. *iters=0L;
  79. acttime[0]=acttime[1]=acttime[2]=0;
  80.  
  81. /* Get a segment for the array */
  82. if(allocmem(SIEVESIZE/16+1,&mysegptr)!=-1)
  83.     return;                /* Allocation failed */
  84.  
  85. /* Loop and execute */
  86. do {
  87.     start_timer();
  88. /*
  89. ** NOTE: If you want to see how many primes the do_sieve() function
  90. ** finds, simply examine its return value.  We don't do that here.
  91. **
  92. ** 4/14/93 - Modified so that sieve performs 25 iterations per
  93. **  call.  RG
  94. */
  95.     do_sieve(mysegptr,SIEVESIZE);
  96.  
  97.     stop_timer(mytime);
  98.  
  99.     /* Accumulate elapsed time into total time */
  100.     accumtime(mytime,acttime);
  101.  
  102.     *iters+=25L;            /* 4/14/93 25 iters per!! */
  103.  
  104.     if(winptr!=NULL)
  105.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  106.  
  107. } while(acttime[2]<dotime);
  108.  
  109. /* Free the array segment */
  110. freemem(mysegptr);
  111.  
  112. }
  113.  
  114. /****************************
  115. *           sort            *
  116. *****************************
  117. ** The Sort benchmark (new and improved!)
  118. ** Call with:
  119. **   sort(winptr,dotime,acttime,iters)
  120. ** Where:
  121. **   winptr= handle of window upon which to draw slidey-bar; null means don't
  122. **   dotime = # of seconds to perform the sort
  123. ** Returns:
  124. **   acttime[3] = pointer to a 3-element array
  125. **                acttime[0]=# of microseconds elapsed
  126. **                acttime[1]=# of milliseconds elapsed
  127. **                acttime[2]=# of seconds elapsed
  128. **   iters = # of iterations completed
  129. **
  130. ** NOTE: Here, a SINGLE iteration is considered to be 1 pass
  131. **       of the quick sort and 1 pass of the shell sort.
  132. */
  133. sort(winptr, dotime,acttime,iters)
  134. win_handle *winptr;        /* current window */
  135. unsigned int dotime;        /* Time to do iterations */
  136. unsigned int acttime[3];    /* Actual elapsed time */
  137. unsigned long *iters;        /* # of iterations */
  138. {
  139. unsigned int mysegptr;        /* Pointer to array segment */
  140. unsigned int mytime[3];        /* Local for elapsed time */
  141. unsigned int rarrayseg;        /* Pointer to random array */
  142.  
  143. /* Clear iterations and actual time */
  144. *iters=0L;
  145. acttime[0]=acttime[1]=acttime[2]=0;
  146.  
  147. /* Allocate memory segments for the arrays */
  148. if(allocmem(SORTSIZE/8+1,&mysegptr)!=-1)
  149.     return;            /* Return if failure */
  150. if(allocmem(SORTSIZE/8+1,&rarrayseg)!=-1)
  151. {    freemem(mysegptr);
  152.     return;            /* Return if failure */
  153. }
  154.  
  155. /* Restart the random number generator */
  156. randnum(1L);
  157.  
  158. /* Fill up the random array */
  159. rload_int_seg(rarrayseg,SORTSIZE,32767);
  160.  
  161. do {
  162.  
  163.     /* Copy random array into local */
  164.     segcopy(mysegptr,rarrayseg,SORTSIZE+SORTSIZE);
  165.  
  166.     start_timer();
  167.  
  168.     /* Do a quicksort */
  169.     do_qsort(mysegptr,0,SORTSIZE);
  170.  
  171.     stop_timer(mytime);
  172.     accumtime(mytime,acttime);
  173.  
  174.     /* Fill the array again */
  175.     segcopy(mysegptr,rarrayseg,SORTSIZE+SORTSIZE);
  176.  
  177.     start_timer();
  178.  
  179.     /* Do a shellsort */
  180.     do_shell(mysegptr,SORTSIZE);
  181.  
  182.     stop_timer(mytime);
  183.     accumtime(mytime,acttime);
  184.  
  185.     *iters+=1L;        /* Increment iterations counter */
  186.  
  187.     if(winptr!=NULL)
  188.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  189.  
  190. } while(acttime[2]<dotime);
  191.  
  192. /* Free the memory segments */
  193. freemem(rarrayseg);
  194. freemem(mysegptr);
  195.  
  196. }
  197.  
  198. /****************************
  199. *      movetest             *
  200. *****************************
  201. ** Executes the string move benchmarks.
  202. ** Call with:
  203. **  dotime = max # of seconds for each test
  204. **  nk = # of K bytes to move
  205. ** Returns:
  206. **  acttime[5][3] = Matrix of results.  First index picks:
  207. **                     0=byte-wide
  208. **                     1=word-wide, odd address
  209. **                     2=word-wide, even address
  210. **                     3=dword-wide, odd address
  211. **                     4=dword-wide, even address
  212. **         The last two are filled only if is386!=0.
  213. **         Second index picks 0=micr, 1=milli, 2=seconds.
  214. ** iters[5] = # of iterations for each test.
  215. */
  216. movetest(winptr, dotime,nk,acttime,iters)
  217. win_handle *winptr;        /* current window */
  218. unsigned int dotime;        /* Time to run each test */
  219. unsigned int nk;        /* K bytes to move */
  220. unsigned int acttime[5][3];    /* Actual elapsed time */
  221. unsigned long iters[5];        /* Iterations for each test */
  222. {
  223. unsigned int ssegptr;        /* Source segment */
  224. unsigned int dsegptr;        /* Destination segment */
  225. unsigned int i,j;            /* Index variables */
  226. unsigned int totloops;        /* processor dependent number of loops */
  227.  
  228. /* Clear out the results arrays */
  229. for(i=0;i<5;i++)
  230. {    iters[i]=0L;
  231.     for(j=0;j<3;j++)
  232.         acttime[i][j]=0;
  233. }
  234.  
  235. /* Allocate source and destination segments */
  236. if(allocmem(nk*64+1,&ssegptr)!=-1) return;
  237. if(allocmem(nk*64+1,&dsegptr)!=-1)
  238. {    freemem(ssegptr);
  239.     return;
  240. }
  241.  
  242. /* Loop through the tests */
  243.  
  244. /* Can we do 386 stuff? */
  245. totloops=(machine_config.proc_type>286)? 5:3;
  246.  
  247. for(i=0; i<totloops; ++i)
  248. {
  249.     moveloop(i,ssegptr,dsegptr,nk,dotime,acttime,iters);
  250.  
  251.     if(winptr!=NULL)
  252.         adjust_bar(winptr, i+1, totloops);  /* slide the bar */
  253.  
  254. }
  255.  
  256. /* Free up segments */
  257. freemem(dsegptr);
  258. freemem(ssegptr);
  259.  
  260. return;
  261. }
  262.  
  263. /****************************
  264. *      moveloop             *
  265. *****************************
  266. * Inner loop of movetest
  267. * i selects which test:
  268. *   0 = byte wide
  269. *   1 = word wide odd boundary
  270. *   2 = word wide even boundary
  271. *   3 = double word wide odd boundary
  272. *   4 = double word wide even boundary
  273. */
  274.  
  275. moveloop(i,seg1,seg2,nk,dotime,acttime,iters)
  276. unsigned int i;        /* Which test to perform */
  277. unsigned int seg1;    /* Segment 1 (source) */
  278. unsigned int seg2;    /* Segment 2 (destination) */
  279. unsigned int nk;    /* Number of K bytes */
  280. unsigned int dotime;    /* Max seconds to do */
  281. unsigned int acttime[5][3];    /* Actual elapsed time */
  282. unsigned long iters[5];    /* Iterations */
  283. {
  284. unsigned int nb;        /* Number of bytes to move */
  285. unsigned int nw;        /* Number of words to move */
  286. unsigned int nd;        /* Number of doublewords to move */
  287. unsigned int soff;        /* Source offset */
  288. unsigned int doff;        /* Destination offset */
  289. unsigned int myactime[3];    /* Local for accumulating time */
  290. unsigned int eltime[3];        /* Local for elapsed time per iteration */
  291.  
  292. /* Clear accumulators */
  293. myactime[0]=myactime[1]=myactime[2]=0;
  294.  
  295. /* Set bytes, words, and doublewords */
  296. nb=nk*1024;            /* Calc number of bytes */
  297. nw=nb>>1;            /* Calc number of words */
  298. nd=nw>>1;            /* Calc number of dwords */
  299.  
  300. /* Set even/odd boundary */
  301. soff=doff=0;
  302. if((i&1)!=0) soff=doff=1;
  303.  
  304. do {
  305. /*
  306. ** The i variable tells us which test to perform.
  307. ** 4/14/93 Each move operations performs 25 iterations RG
  308. */
  309.     switch(i) {
  310.  
  311.     case 0:        /* Byte wide */
  312.         start_timer();
  313.         do_bmove(seg1,soff,seg2,doff,nb);
  314.         stop_timer(eltime);
  315.         break;
  316.  
  317.     case 1:        /* Word wide odd */
  318.     case 2:        /* Word wide even */
  319.         start_timer();
  320.         do_wmove(seg1,soff,seg2,doff,nw);
  321.         stop_timer(eltime);
  322.         break;
  323.  
  324.     case 3:        /* Dword wide odd */
  325.     case 4:        /* Dword wide even */
  326.         start_timer();
  327.         do_dmove(seg1,soff,seg2,doff,nd);
  328.         stop_timer(eltime);
  329.         break;
  330.  
  331.     default:
  332.         break;
  333.  
  334.     }    /* End of switch */
  335.  
  336.     accumtime(eltime,myactime);
  337.     iters[i]+=25L;        /* 25 iterations!! */
  338. } while(myactime[2]<dotime);
  339.  
  340. acttime[i][0]=myactime[0]; acttime[i][1]=myactime[1];
  341. acttime[i][2]=myactime[2];
  342. return;
  343. }
  344.  
  345. /****************************
  346. *      ifourbang            *
  347. *****************************
  348. ** Integer math tests.
  349. ** Note, n indicates the number of times each 4 operations
  350. ** (add, subtract, multiply, and divide) are performed.
  351. ** Maximum is 8192.
  352. */
  353. ifourbang(winptr, dotime, n, acttime,iters)
  354. win_handle *winptr;        /* current window handlke */
  355. unsigned int dotime;        /* Seconds to perform operations */
  356. unsigned int n;            /* number of operations */
  357. unsigned int acttime[3];    /* Actual elapsed time */
  358. unsigned long *iters;        /* Iterations completed */
  359. {
  360. unsigned int i;            /* Index */
  361. unsigned int rn;        /* Random number */
  362. unsigned int mysegptr;        /* Pointer to working segment */
  363. unsigned int huge *isegptr;    /* Actual pointer to rands */
  364. unsigned int mytime[3];        /* Local for elapsed time */
  365.  
  366.  
  367. /* Clear iterations and actual time */
  368. *iters=0;
  369. acttime[0]=acttime[1]=acttime[2]=0;
  370.  
  371. /* Allocate memory segments for the arrays */
  372. if(allocmem(n/2,&mysegptr)!=-1)
  373.     return;            /* Return if failure */
  374.  
  375. /* Build the random array */
  376. isegptr=MK_FP(mysegptr,0);
  377. i=0;
  378. do {
  379.     if(i==0) *(isegptr+i)=2;
  380.     else *(isegptr+i)=*(isegptr+i-1)+1;
  381.     ++i;
  382.     *(isegptr+i)=*(isegptr+i-1)-1; ++i;
  383.     *(isegptr+i)=*(isegptr+i-1)+2; ++i;
  384.     *(isegptr+i)=*(isegptr+i-1)-1; ++i;
  385. } while(i<(n*4));
  386.  
  387. do {
  388.     start_timer();
  389.  
  390. /*
  391. ** 4/14/93 Each ifourbang() call performs 10 iterations RG
  392. */
  393.     do_ifourbang(mysegptr,n);
  394.  
  395.     stop_timer(mytime);
  396.     accumtime(mytime,acttime);
  397.     *iters+=10L;
  398.  
  399.     if(winptr!=NULL)
  400.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  401.  
  402. }while(acttime[2]<dotime);
  403.  
  404. /* Free memory segments */
  405. freemem(mysegptr);
  406. }
  407.  
  408. /****************************
  409. *      ffourbang            *
  410. *****************************
  411. ** Floating-point version of ifourbang.
  412. */
  413. ffourbang(winptr,dotime,acttime,iters)
  414. win_handle *winptr;        /* current window handle */
  415. unsigned int dotime;        /* # of seconds to do the test */
  416. unsigned int acttime[3];    /* Actual elapsed time */
  417. unsigned long *iters;        /* # of iterations */
  418. {
  419. unsigned int mytime[3];        /* Local for elapsed time */
  420.  
  421. /* Clear iterations and actual time */
  422. *iters=0L;
  423. acttime[0]=acttime[1]=acttime[2]=0;
  424.  
  425. do {
  426.     start_timer();
  427.     do_fourbang(FFITERS);
  428.     stop_timer(mytime);
  429.     accumtime(mytime,acttime);
  430.     *iters+=1L;
  431.  
  432.     if(winptr!=NULL)
  433.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  434.  
  435. } while(acttime[2]<dotime);
  436. }
  437.  
  438. /****************************
  439. *       fourier             *
  440. *****************************
  441. ** Calculates fourier coefficients for a square wave.
  442. */
  443. fourier(winptr, dotime,acttime,iters)
  444. win_handle *winptr;        /* current window handle */
  445. unsigned int dotime;        /* Time to do test */
  446. unsigned int acttime[3];    /* Actual elapsed time */
  447. unsigned long *iters;        /* Iterations */
  448. {
  449. double coeffs[NCOEFFS*2];    /* Coefficients array */
  450. unsigned int mytime[3];        /* Local time */
  451.  
  452. /* Clear iterations and actual time */
  453. *iters=0L;
  454. acttime[0]=acttime[1]=acttime[2]=0;
  455.  
  456. do{
  457.     start_timer();
  458. /*
  459. ** 4/14/93 Each square_fourier() call performs 25 iterations RG
  460. */
  461.     square_fourier(NCOEFFS,coeffs);
  462.     stop_timer(mytime);
  463.     accumtime(mytime,acttime);
  464.     *iters+=25L;
  465.  
  466.     if(winptr!=NULL)
  467.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  468.  
  469. } while(acttime[2]<dotime);
  470. }
  471.  
  472. /****************************
  473. *       textbench           *
  474. *****************************
  475. ** Random text display benchmark (cursor positioning)
  476. ** This routine tests appropriate modes.
  477. */
  478. textbench(dotime,n,avgips)
  479. unsigned int dotime;        /* # of seconds to do the test */
  480. unsigned int n;            /* # of characters to display */
  481. double *avgips;            /* average iterations per second */
  482.  
  483. {
  484. /* Maximum column # */
  485. unsigned int acttime[3][3];    /* Actual elapsed time */
  486. unsigned long iters[3];        /* Iterations */
  487. unsigned int cmax[3]={80,80,80};
  488. unsigned int modes[3]={2,3,7};
  489. unsigned int nummodes;
  490. unsigned int vpage;        /* Video page segment */
  491. unsigned int rcseg;        /* Row/column segment number */
  492. unsigned int attseg;        /* Attributes segment */
  493. int i,j;            /* Indices */
  494. unsigned char far *attsegptr;    /* Far pointer to attribute seg */
  495. unsigned int mytime[3];        /* Local for elapsed time */
  496.  
  497. /* just for looks */
  498. clearscreen();
  499. printf("Preparing text benchmarks ...");
  500.  
  501. /* set modes according to type */
  502.  
  503. switch(machine_config.graphics_type){
  504.     case MDA:
  505.     case HERC:
  506.             nummodes=1;
  507.             modes[0]=7;
  508.             break;
  509.     case CGA:
  510.             nummodes=2;
  511.             break;
  512.     case EGAM:
  513.     case EGAC:
  514.     case VGA:
  515.             nummodes=3;
  516.             break;
  517. }
  518.  
  519. /* Clear all the accumulators */
  520. for(i=0;i<3;i++)
  521. {    iters[i]=0L;
  522.     for(j=0;j<3;j++)
  523.     acttime[i][j]=0;
  524. }
  525. /* Allocate the row/column and attributes segments */
  526. if(allocmem(n/8+1,&rcseg)!=-1)
  527.     return;
  528. if(allocmem(n/16+1,&attseg)!=-1)
  529. {    freemem(rcseg);
  530.     return;
  531. }
  532.  
  533. /* Restart the random number generator */
  534. randnum(1L);
  535.  
  536. /* Fill the attributes segment */
  537. attsegptr=MK_FP(attseg,0);
  538. for(i=0;i<n;i++)
  539.     *(attsegptr+i)=(unsigned char)randwc(256L);
  540.  
  541.  
  542. /* Loop through the tests */
  543. clearscreen();
  544. for(i=0;i<nummodes;i++)
  545. {    textbloop(dotime,n,mytime,&iters[i],modes[i],cmax[i],rcseg,attseg);
  546.     acttime[i][0]=mytime[0];
  547.     acttime[i][1]=mytime[1];
  548.     acttime[i][2]=mytime[2];
  549. }
  550.  
  551. /* Clean up after yourself */
  552. freemem(attseg);
  553. freemem(rcseg);
  554.  
  555. /* calculate avgips */
  556.  
  557. *avgips=0;
  558. for(i=0;i<nummodes;i++){
  559.     *(avgips)+=((double)iters[i])/timetodouble(acttime[i]);
  560.     }
  561. *avgips/=nummodes;
  562.  
  563. return;
  564. }
  565.  
  566. /****************************
  567. *       textbloop           *
  568. *****************************
  569. ** Inner loop for the random text benchmark.
  570. */
  571. textbloop(dotime,n,acttime,iters,vmode,cmax,rcseg,attseg)
  572. unsigned int dotime;        /* Max seconds to execute */
  573. unsigned int n;            /* Number of entries */
  574. unsigned int acttime[3];    /* Actual time */
  575. unsigned long *iters;        /* Iterations */
  576. unsigned int vmode;        /* Graphics mode */
  577. unsigned int cmax;        /* Column max */
  578. unsigned int rcseg;        /* Row/column segment */
  579. unsigned int attseg;        /* Attributes segment */
  580. {
  581. unsigned int vpage;        /* Video page segment */
  582. unsigned int far *rcsptr;    /* Pointer to row/col segment */
  583. unsigned int eltime[3];        /* Holding for elapsed time */
  584. unsigned int i;            /* Index */
  585. unsigned int myvmode;        /* Saved video mode */
  586.  
  587. /* just for looks */
  588. printf("Running random text benchmark ...");
  589.  
  590. /* Build far pointer */
  591. rcsptr=MK_FP(rcseg,0);
  592.  
  593. /* Fill up the row/column segment */
  594. for(i=0;i<n;i++)
  595. {    *(rcsptr+i)=(unsigned int)(abs((randwc(25L)<<8))+
  596.         abs(randwc((long)cmax)));
  597. }
  598.  
  599. /* Determine the video page segment */
  600. vpage=0;
  601.  
  602. /* Get the current video mode and save it */
  603. myvmode=gvmode();
  604.  
  605. /* Put the system in the proper video mode */
  606. svmode(vmode);
  607.  
  608. /* Clear accumulators */
  609. *iters=0L;
  610. acttime[0]=acttime[1]=acttime[2]=0;
  611.  
  612. /* Do the benchmark */
  613. do {
  614.     start_timer();
  615. /*
  616. ** This version modified to run 20 loops of the benchmark
  617. ** with each call to random_text  4/14/93 RG
  618. */
  619.     random_text(rcseg,attseg,n,vpage);
  620.     stop_timer(eltime);
  621.     accumtime(eltime,acttime);
  622.     *iters+=20L;        /* Bump iterations */
  623.     svmode(vmode);        /* Clear the screen */
  624. } while(acttime[2]<dotime);
  625.  
  626. /* Return the system to original mode */
  627. svmode(myvmode);
  628.  
  629. return;
  630. }
  631.  
  632. /****************************
  633.  *       tscroll             *
  634. *****************************
  635. * Text scrolling benchmark
  636. */
  637. tscroll(dotime,n,avgips)
  638. unsigned int dotime;        /* # of seconds to do each test */
  639. unsigned int n;            /* # of characters to display */
  640. double *avgips;            /* average iterations for modes */
  641. {
  642. /* Maximum column # */
  643. unsigned int acttime[3][3];    /* Actual elapsed time */
  644. unsigned long iters[3];        /* Iterations */
  645. unsigned int cmax[3]={80,80,80};
  646. unsigned int modes[3]={2,3,7};
  647. unsigned int nummodes;
  648. unsigned int rcseg;        /* Row/column/attr segment */
  649. unsigned int i,j;        /* Indices */
  650. unsigned int mytime[3];
  651.  
  652. /* set modes according to type */
  653.  
  654. switch(machine_config.graphics_type){
  655.     case MDA:
  656.     case HERC:
  657.             nummodes=1;
  658.             modes[0]=7;
  659.             break;
  660.     case CGA:
  661.             nummodes=2;
  662.             break;
  663.     case EGAM:
  664.     case EGAC:
  665.     case VGA:
  666.             nummodes=3;
  667.             break;
  668. }
  669.  
  670. /* Clear all the accumulators */
  671. for(i=0;i<3;i++)
  672. {    iters[i]=0L;
  673.     for(j=0;j<3;j++)
  674.     acttime[i][j]=0;
  675. }
  676.  
  677. /* Allocate memory for the row/column,attribute segments */
  678. if(allocmem(n*3/8+1,&rcseg)!=-1) return;
  679.  
  680. /* Restart the random number generator */
  681. randnum(1L);
  682.  
  683. /* Loop through the tests */
  684. for(i=0;i<nummodes;i++)
  685. {
  686.     scrolloop(dotime,n,mytime,&iters[i],modes[i],cmax[i],rcseg);
  687.     acttime[i][0]=mytime[0];
  688.     acttime[i][1]=mytime[1];
  689.     acttime[i][2]=mytime[2];
  690. }
  691.  
  692. /* Clean up after yourself */
  693. freemem(rcseg);
  694.  
  695. /* calculate avgips */
  696.  
  697. *avgips=0;
  698. for(i=0;i<nummodes;i++){
  699.     *avgips+=(double)iters[i]/timetodouble(acttime[i]);
  700.     }
  701. *avgips/=nummodes;
  702.  
  703. return;
  704. }
  705.  
  706. /****************************
  707. *       scrolloop           *
  708. *****************************
  709. * Inner loop for the text scroll benchmark.
  710. */
  711. scrolloop(dotime,n,acttime,iters,vmode,cmax,rcseg)
  712. unsigned int dotime;        /* Max seconds to execute */
  713. unsigned int n;            /* Size of rcseg array */
  714. unsigned int acttime[3];    /* Actual elapsed time */
  715. unsigned long *iters;        /* Iterations completed */
  716. unsigned int vmode;        /* Video mode */
  717. unsigned int cmax;        /* Column max */
  718. unsigned int rcseg;        /* Row/column/attribute segment */
  719. {
  720. unsigned int vpage;        /* Video page */
  721. unsigned int far *rcsptr;    /* Pointer to row/column segment */
  722. unsigned int eltime[3];        /* Local for elapsed time */
  723. unsigned int i,j;        /* Indices */
  724. unsigned int myvmode;        /* Local for current video mode */
  725. unsigned int ulr,ulc,lrr,lrc;    /* Corner coordinates for window */
  726.  
  727. /* just for looks */
  728. printf("Running scroll benchmark ...");
  729.  
  730. /* Build the row/column/attributes array */
  731. rcsptr=MK_FP(rcseg,0);
  732. for(i=0;i<n;i++)
  733. {
  734.     j=3*i;
  735.     ulr=(unsigned int)abs(randwc(24L));
  736.     ulc=(unsigned int)abs(randwc((long)(cmax-1)));
  737.     lrr=ulr+(unsigned int)abs(randwc(24L-(long)ulr));
  738.     lrc=ulc+(unsigned int)abs(randwc((long)(cmax-ulc-1)));
  739.     *(rcsptr+j)=(ulr<<8)+ulc;
  740.     *(rcsptr+j+1)=(lrr<<8)+lrc;
  741.     lrc=(unsigned int)abs(randwc(256L));    /* Attributes */
  742.     ulc=(unsigned int)abs(randwc((long)(lrr-ulr+1)));
  743.     *(rcsptr+j+2)=(lrc<<8)+ulc;
  744. }
  745.  
  746. /* Set video page */
  747. vpage=0;
  748.  
  749. /* Get the current video mode */
  750. myvmode=gvmode();
  751.  
  752. /* Put the system in the proper video mode */
  753. svmode(vmode);
  754.  
  755. /* Clear the accumulators */
  756. *iters=0L;
  757. acttime[0]=acttime[1]=acttime[2]=0;
  758.  
  759. /* Do the benchmark */
  760. do {
  761.     start_timer();
  762. /*
  763. ** This version modified to perform 20 iterations with each
  764. ** call to scroll_text.  4/14/93  RG
  765. */
  766.     scroll_text(rcseg,n>>1,vpage);
  767.     stop_timer(eltime);
  768.     svmode(vmode);        /* Clear display */
  769.     *iters+=20L;        /* Bump iterations */
  770.     accumtime(eltime,acttime);
  771. } while(acttime[2]<dotime);
  772.  
  773. /* Return system to original mode */
  774. svmode(myvmode);
  775.  
  776. return;
  777. }
  778.  
  779. /****************************
  780. *     graph_bench           *
  781. *****************************
  782. ** Do the graphics filled-circle benchmark.
  783. ** The results array is a 2-dimensional array that has the following
  784. ** format:
  785. **   results[i][j]        i -> picks a group
  786. **                              j -> picks member of group.
  787. **   Each group is 5 elements big.
  788. **     results[i][0] = mode
  789. **     results[i][1]= # iterations completed
  790. **     results[i][2]= microseconds elapsed
  791. **     results[i][3]= milliseconds elapsed
  792. **     retuslt[i][4]= seconds elapsed
  793. */
  794. graph_bench(dotime, avgips)
  795. unsigned int dotime;        /* Max seconds for each test */
  796. double *avgips;
  797. {
  798. unsigned long results[11][5];    /* Results array */
  799. unsigned int rcvert[3];        /* For converting results */
  800. int i,j;            /* Indices */
  801. int gatype;            /* Graphics adaptor type */
  802. int mvector[11];        /* Mode vector */
  803. int nmodes;            /* Number of modes in vector */
  804. int cx,cy;            /* Center of circle */
  805. int color;            /* Foreground color */
  806. unsigned int esseg;        /* Graphics segment */
  807. unsigned int floodseg;        /* Segment for flood routine */
  808. unsigned int acttime[3];    /* Time accumulator */
  809. unsigned int eltime[3];        /* Elapsed time per loop */
  810. unsigned long iters;        /* Iterations */
  811. int mymode;            /* Storage for current mode */
  812. union REGS myregs;
  813. struct SREGS mysregs;
  814.  
  815. /* Clear results array */
  816. for(i=0;i<11;i++)
  817.     for(j=0;j<5;j++)
  818.         results[i][j]=0;
  819.  
  820. /* Allocate memory for the flood segment (16K should be more
  821. ** than enough) */
  822. if(allocmem(1024,&floodseg)!=-1) return;
  823.  
  824. /* Determine what type of graphics adaptor we've got. */
  825. if((gatype=machine_config.graphics_type)==0) {
  826.     *avgips=0;
  827.     return;
  828.     }
  829.  
  830. /* Load up the modes vector */
  831. build_mvector(gatype,&nmodes,mvector);
  832. if(nmodes==0){
  833.     *avgips=0;
  834.     return;
  835.     }
  836.  
  837. /* Loop through each of the modes in the vector */
  838. for(i=0;i<nmodes;i++)
  839. {
  840.     mymode=gvmode();            /* Get current mode */
  841.     acttime[0]=acttime[1]=acttime[2]=0;    /* Clear acc. time */
  842.     iters=0L;
  843.     setup_circle(mvector[i],&cx,&cy,&color,&esseg);
  844.     do {
  845.         svmode(mvector[i]);
  846.         /* If graphics mode 4, set pallette */
  847.         if(mvector[i]==4)
  848.         {
  849.             myregs.h.ah=0x0B;
  850.             myregs.x.bx=257;
  851.             intdosx(&myregs,&myregs,&mysregs);
  852.         }
  853.  
  854.         start_timer();
  855.         circle_fill(cx,cy,color,mvector[i],floodseg,esseg);
  856.         stop_timer(eltime);
  857.         accumtime(eltime,acttime);
  858.         iters++;
  859.     } while(acttime[2]<dotime);
  860.     svmode(mymode);            /* Restore mode */
  861.  
  862. /* Put results into results array */
  863.     results[i][0]=mvector[i];    /* Mode */
  864.     results[i][1]=iters;        /* Iterations */
  865.     results[i][2]=acttime[0];    /* Microseconds */
  866.     results[i][3]=acttime[1];    /* Milliseconds */
  867.     results[i][4]=acttime[2];    /* Seconds */
  868. }
  869.  
  870. /* All done, release the flood segment */
  871. freemem(floodseg);
  872.  
  873. /* calculate avgips */
  874.  
  875. *avgips=0;
  876. for(i=0;i<nmodes;i++){
  877.     rcvert[1]=(unsigned int)(results[i][2] & 0x0FFFFL);
  878.     rcvert[2]=(unsigned int)(results[i][3] & 0x0FFFFL);
  879.     rcvert[3]=(unsigned int)(results[i][4] & 0x0FFFFL);
  880.     *avgips=*avgips+(double)results[i][1]/timetodouble(rcvert);
  881.     }
  882. *avgips/=nmodes;
  883.  
  884. return;
  885. }
  886.  
  887. /****************************
  888. *    circle_fill            *
  889. *****************************
  890. * Performs the circle fill algorithm.
  891. */
  892. circle_fill(cx,cy,color,mode,floodseg,esseg)
  893. int cx,cy;        /* Coordinates of center */
  894. int color;        /* Foreground color */
  895. int mode;        /* Graphics mode */
  896. unsigned int floodseg;    /* Segment for flood stack */
  897. unsigned int esseg;    /* Grahics segment */
  898. {
  899. int radius;        /* Circle radius */
  900. int i;            /* Index */
  901.  
  902. radius=8;        /* Starting radius */
  903.  
  904. /* Draw an initial circle */
  905. draw_circle(cx,cy,radius,color,mode,esseg);
  906.  
  907. /* Draw and fill the rest */
  908. for(i=0;i<NUMCIRC;++i) {
  909.     radius+=8;
  910.     draw_circle(cx,cy,radius,color,mode,esseg);
  911.     do_flood(cx+radius-4,cy,color,mode,floodseg,esseg);
  912. }
  913. return;
  914. }
  915.  
  916. /****************************
  917. *    setup_circle           *
  918. *****************************
  919. * Setup variables needed to draw a circle.
  920. */
  921. setup_circle(mode,cx,cy,color,esseg)
  922. int mode;        /* Grahics mode */
  923. int *cx,*cy;        /* Center of circle (returned) */
  924. int *color;        /* Color (returned) */
  925. unsigned int *esseg;    /* ES segment for drawing (returned) */
  926. {
  927.  
  928.     switch(mode) {
  929.  
  930.         case 4:
  931.         case 5:    *cx=160;
  932.             *cy=100;
  933.             *color=3;
  934.             *esseg=0xB800;
  935.             return;
  936.         case 6:    *cx=320;
  937.             *cy=100;
  938.             *color=1;
  939.             *esseg=0xB800;
  940.             return;
  941.         case 13:
  942.             *cx=160;
  943.             *cy=100;
  944.             *color=7;
  945.             *esseg=0xA000;
  946.             return;
  947.         case 14:
  948.             *cx=320;
  949.             *cy=100;
  950.             *color=15;
  951.             *esseg=0xA000;
  952.             return;
  953.         case 15:
  954.             *cx=320;
  955.             *cy=175;
  956.             *color=1;
  957.             *esseg=0xA000;
  958.             return;
  959.         case 16:
  960.             *cx=320;
  961.             *cy=175;
  962.             *color=3;
  963.             *esseg=0xA000;
  964.             return;
  965.         case 17:
  966.         case 18:
  967.             *cx=320;
  968.             *cy=240;
  969.             *color= (mode==17) ? 1 : 15;
  970.             *esseg=0xA000;
  971.             return;
  972.         case 19:
  973.             *cx=160;
  974.             *cy=100;
  975.             *color=15;
  976.             *esseg=0xA000;
  977.             return;
  978.         case 255:
  979.             *cx=360;
  980.             *cy=174;
  981.             *color=1;
  982.             *esseg=0xB000;
  983.             return;
  984.     }
  985. }
  986.  
  987. /****************************
  988. *     build_mvector         *
  989. *****************************
  990. ** Builds a mode vector.
  991. ** Pass in a graphics adaptor type, this routine returns a vector
  992. ** of video modes that the adaptor can support.
  993. */
  994. build_mvector(gatype,n,vector)
  995. int gatype;        /* Graphics adaptor type */
  996. int *n;            /* Returned length of vector */
  997. int vector[];        /* Vector of supported modes */
  998. {
  999. int i;            /* Index */
  1000.  
  1001. switch(gatype) {
  1002.     case 0:            /* NO graphics adaptor! */
  1003.         *n=0;
  1004.         return;
  1005.  
  1006.     case 1:            /* VGA */
  1007.         vector[0]=4; vector[1]=5; vector[2]=6;
  1008.         vector[3]=13; vector[4]=14; vector[5]=15;
  1009.         vector[6]=16; vector[7]=17;vector[8]=18;
  1010.         vector[9]=19;
  1011.         *n=10;
  1012.         return;
  1013.  
  1014.     case 2:            /* EGA enhanced */
  1015.         vector[0]=4; vector[1]=5; vector[2]=6;
  1016.         vector[3]=13; vector[4]=14;
  1017.         vector[5]=16;
  1018.         *n=6;
  1019.         return;
  1020.  
  1021.     case 3:            /* CGA */
  1022.         vector[0]=4; vector[1]=5; vector[2]=6;
  1023.         *n=3;
  1024.         return;
  1025.  
  1026.     case 4:            /* EGA monochrome */
  1027.         vector[0]=6; vector[1]=15;
  1028.         *n=2;
  1029.         return;
  1030.  
  1031.     case 5:            /* Hercules */
  1032.         vector[0]=255;
  1033.         *n=1;
  1034.         return;
  1035.  
  1036.     case 6:            /* MDA */
  1037.     default:
  1038.         *n=0;
  1039.         return;
  1040. }
  1041. }
  1042.  
  1043. /****************************
  1044. *      do_fileio            *
  1045. *****************************
  1046. * Performs the file i/o benchmark.
  1047. */
  1048. do_fileio(winptr,dotime,rbytes,wbytes,accrtime,accwtime,maxbytes)
  1049. win_handle *winptr;        /* current window */
  1050. unsigned int dotime;        /* User-selected time */
  1051. unsigned long *rbytes;        /* Total bytes read */
  1052. unsigned long *wbytes;        /* Total bytes written */
  1053. unsigned int accrtime[3];    /* Accumulated read time */
  1054. unsigned int accwtime[3];    /* Accumulated write time */
  1055. unsigned long maxbytes;        /* Maximum bytes avail */
  1056. {
  1057. unsigned int buffseg;        /* Buffer segment for reading/writing */
  1058. unsigned int i;            /* Index */
  1059. char huge *buffptr;        /* Pointer to buffer */
  1060. unsigned long mymax;        /* My accumulated maximum */
  1061.  
  1062. /* Clear all the results */
  1063. *rbytes=0L;
  1064. *wbytes=0L;
  1065. accrtime[0]=accrtime[1]=accrtime[2]=0;
  1066. accwtime[0]=accwtime[1]=accwtime[2]=0;
  1067.  
  1068. /* Allocate a buffer segment (if you can) */
  1069. if(allocmem(2500+1,&buffseg)!=-1) return;
  1070. buffptr=(char huge *) MK_FP(buffseg,0);
  1071.  
  1072. /* Fill up the memory segment */
  1073. for(i=0;i<40000;i++)
  1074.     *buffptr++='A';
  1075.  
  1076. /* Initialize maximum */
  1077. mymax=0L;
  1078.  
  1079. /* Create the files */
  1080. for (i=0;i<20;i++)
  1081.     kreate(i,buffseg,&mymax);
  1082.  
  1083. /* Extend them */
  1084. for(i=0;i<20;i++)
  1085.     appnd(i,buffseg,&mymax);
  1086.  
  1087. randnum(1L);
  1088.  
  1089. /* Do random i/o */
  1090. random_fio(winptr,dotime,buffseg,rbytes,wbytes,accrtime,accwtime,
  1091.         maxbytes,&mymax);
  1092.  
  1093. /* Clean up after yourself */
  1094. freemem(buffseg);
  1095. for(i=0;i<20;i++)
  1096.     remove(gfname(i));
  1097.  
  1098. return;
  1099. }
  1100.  
  1101. /****************************
  1102. *         kreate            *
  1103. *****************************
  1104. *  Create file n.  Write the assigned number of bytes to
  1105. *  the file and close it.  Accumulate the number of bytes
  1106. *  written and the aggregate time.
  1107. */
  1108. kreate(n,buffseg,mymax)
  1109. int n;                /* File number */
  1110. unsigned int buffseg;        /* Pointer to buffer segment */
  1111. unsigned long *mymax;        /* Bytes written */
  1112. {
  1113. int fh;                /* File handle */
  1114. unsigned int nb;        /* # of bytes to write */
  1115. unsigned int wvector[20]={4000,1000,500,2800,2500,
  1116.             1400,8000,8800,300,21111,
  1117.             2000,6000,200,48800,1300,
  1118.             9870,3000,2816,8660,127};
  1119.  
  1120. /* Open the file */
  1121. fh=ll_create(gfname(n));
  1122. nb=wvector[n];            /* Number of bytes to write */
  1123. ll_seekwrite(fh,0L,0,buffseg,nb);    /* Do the write */
  1124. *mymax+=(unsigned long)nb;    /* Accumulate bytes written */
  1125. ll_close(fh);            /* Close the file */
  1126. return;
  1127. }
  1128.  
  1129. /****************************
  1130. *        appnd              *
  1131. *****************************
  1132. * This routine opens file n and appends the appropriate number of
  1133. * bytes.
  1134. */
  1135. appnd(n,buffseg,mymax)
  1136. int n;                /* File number */
  1137. unsigned int buffseg;        /* Buffer segment */
  1138. unsigned long *mymax;        /* Total bytes written */
  1139. {
  1140. int fh;                /* File handle */
  1141. unsigned int nb;        /* Number of bytes */
  1142. unsigned int wvector[20]={1200,2030,31111,3400,9099,
  1143.             2075,7000,400,2200,2700,
  1144.             2360,1495,5960,3430,70,
  1145.             3600,8900,1233,4000,1000};
  1146.  
  1147. fh=ll_open(gfname(n));        /* Open the file */
  1148. nb=wvector[n];            /* Number of bytes to write */
  1149. ll_seekwrite(fh,0L,2,buffseg,nb);    /* Do the write */
  1150. *mymax+=(unsigned long)nb;    /* Accumulate bytes written */
  1151. ll_close(fh);            /* Close the file */
  1152. return;
  1153. }
  1154.  
  1155. /****************************
  1156. *       random_fio          *
  1157. *****************************
  1158. * This is the random i/o portion of the file i/o benchmark.
  1159. * The routine randomly selects, reads, and writes the 20
  1160. * files.  The system continues the testing until the aggregate
  1161. * time (read and write) exceed the selected time (dotime)
  1162. */
  1163. random_fio(winptr, dotime,buffseg,rbytes,wbytes,accrtime,accwtime,
  1164.         maxbytes,mymax)
  1165. win_handle *winptr;            /* current window */
  1166. unsigned int dotime;            /* User selected time */
  1167. unsigned int buffseg;            /* Read/write buffer segment */
  1168. unsigned long *wbytes;            /* Total bytes written */
  1169. unsigned long *rbytes;            /* Total bytes read */
  1170. unsigned int accwtime[3];        /* Total write-time */
  1171. unsigned int accrtime[3];        /* Total read-time */
  1172. unsigned long maxbytes;            /* Max space avail. */
  1173. unsigned long *mymax;
  1174. {
  1175. int fh;                    /* File handle */
  1176. unsigned long offset;            /* Byte offset */
  1177. unsigned long flen;            /* File length */
  1178. unsigned int eltime[3];            /* Elapsed time */
  1179. unsigned int nb;            /* Number of bytes */
  1180. int n;                    /* File number */
  1181. int i;                    /* Loop index */
  1182. unsigned long avg;            /* Avg. bytes read per loop */
  1183.  
  1184. do {
  1185.     avg=0L;                /* Clear averaging var. */
  1186.  
  1187.     /* For each pass, do 3 reads and 1 write */
  1188.     for(i=0;i<3;i++)
  1189.     {
  1190.         n=(int)abs(randwc(20L));
  1191.         fh=ll_open(gfname(n));
  1192.         flen=ll_filelen(fh);        /* Get file length */
  1193.         offset=abs(randwc(flen));    /* Get random offset */
  1194.         flen=flen-offset;
  1195.         if(flen==0L) ++flen;
  1196.         nb=(flen>32000L) ? 32000 : (unsigned int)flen;
  1197.         nb=(unsigned int)abs(randwc((unsigned long)nb));
  1198.         start_timer();            /* Start timing */
  1199.         ll_seekread(fh,offset,0,buffseg,nb);
  1200.         stop_timer(eltime);
  1201.         accumtime(eltime,accrtime);
  1202.         *rbytes+=(unsigned long)nb;
  1203.         avg+=(unsigned long)nb;
  1204.         ll_close(fh);
  1205.     }
  1206.  
  1207.     n=(int)abs(randwc(20L));        /* No resonance */
  1208.     n=(int)abs(randwc(20L));        /* Pick file */
  1209.     fh=ll_open(gfname(n));
  1210.     flen=ll_filelen(fh);            /* Get file length */
  1211.     offset=abs(randwc(flen));        /* Get random offset */
  1212.     nb=(unsigned int)(avg/3L);
  1213.     if((offset+(unsigned long)nb)>flen)
  1214.     {    *mymax+=((offset+(unsigned long)nb)-flen);
  1215.         if(*mymax>maxbytes) return;
  1216.     }
  1217.     start_timer();                /* Start timing */
  1218.     ll_seekwrite(fh,offset,0,buffseg,nb);    /* Do the write */
  1219.     stop_timer(eltime);            /* Done timing */
  1220.     accumtime(eltime,accwtime);
  1221.     *wbytes+=(unsigned long)nb;
  1222.     ll_close(fh);
  1223.  
  1224.     if(winptr!=NULL)
  1225.         adjust_bar(winptr, accrtime[2]+accwtime[2], dotime); /* bar */
  1226.  
  1227. } while(accrtime[2]+accwtime[2]<dotime);
  1228. return;
  1229.  
  1230. }
  1231.  
  1232. /****************************
  1233. *     gfname                *
  1234. *****************************
  1235. ** For file i/o routines.  Pass this guy and integer between
  1236. ** 0 and 19 and he returns a pointer to a null-terminated string
  1237. ** holding the file's name.
  1238. */
  1239. char *gfname(n)
  1240. int n;            /* Selection number */
  1241. {
  1242. static char fname[20];    /* File name buffer */
  1243.  
  1244. /* Build the name */
  1245. strcpy(fname,"BYTEDAT.");
  1246. itoa(n,fname+8,10);
  1247.  
  1248. return(fname);
  1249. }
  1250.  
  1251. /****************************
  1252. *     ll_diskseek           *
  1253. *****************************
  1254. ** Low level disk seek benchmark (hard disks)
  1255. ** NOTE: This test requires that the throughput test be already
  1256. ** run so that bytes per second is available.
  1257. */
  1258. ll_diskseek(drive,bytespersec,seektime)
  1259. unsigned int drive;        /* Drive number (0=1st hard disk) */
  1260. double bytespersec;        /* Bytes per sec from throughput test */
  1261. double *seektime;        /* Avg seek time */
  1262. {
  1263. unsigned int buffseg;        /* Buffer segment */
  1264. harddiskspecs myhdisk;        /* Hard disk specs */
  1265. unsigned int mytime[3];        /* Local for elapsed time */
  1266. unsigned int i;            /* Index */
  1267. double divisor;
  1268. double transtime;
  1269. double thistime;
  1270.  
  1271.  
  1272. /* Allocate memory segments for the arrays */
  1273. if(allocmem(512/16+1,&buffseg)!=-1)
  1274.     return;
  1275.  
  1276. /* Determine the drive's maximum cylinder number */
  1277. if(get_hdinfo(drive+0x80,&myhdisk)==0)
  1278. {    freemem(buffseg);
  1279.     return;
  1280. }
  1281. divisor=(long)myhdisk.maxcyl*(long)(myhdisk.maxcyl-1);
  1282. transtime=(double)512.0/bytespersec;
  1283. drive +=0x80;                /* Hard disk */
  1284. for(i=1;i<myhdisk.maxcyl;i++)
  1285. {    hd_1seek(drive,0,buffseg);    /* Seek to 0 */
  1286.     start_timer();
  1287.     hd_1seek(drive,i,buffseg);    /* Seek distance=i */
  1288.     stop_timer(mytime);
  1289.     thistime=timetodouble(mytime);    /* Get time */
  1290.     thistime-=transtime;        /* Subtract transfer time */
  1291.     thistime=thistime*((double)(myhdisk.maxcyl-i)/(double)divisor);
  1292.     *(seektime)+=thistime+thistime;    /* Times 2 */
  1293. }
  1294.  
  1295. /* Free memory segments */
  1296. freemem(buffseg);
  1297.  
  1298. return;
  1299. }
  1300.  
  1301. /****************************
  1302. *     ll_hdthru             *
  1303. *****************************
  1304. ** Low level hard disk read throughput.
  1305. */
  1306. ll_hdthru(drive,n,bpersec)
  1307. unsigned int drive;        /* Drive to test */
  1308. unsigned int n;            /* # of iterations to test */
  1309. double *bpersec;        /* Bytes per second transfer */
  1310. {
  1311. unsigned int cysecarrseg;    /* Cylinder/array segment */
  1312. unsigned int buffseg;        /* Buffer segment */
  1313. harddiskspecs myhdisk;        /* Hard disk specs */
  1314. unsigned int far *cysecptr;    /* Far pointer to cyl/sect array */
  1315. unsigned int eltime[3];        /* Local for elapsed time */
  1316. unsigned int seektime1[3];
  1317. unsigned int seektime2[3];
  1318. unsigned int cyl;        /* Cylinder */
  1319. unsigned int sect;        /* Sector */
  1320. unsigned long totbytes;        /* Total bytes */
  1321. unsigned int i;            /* Index */
  1322.  
  1323. /* Clear return value */
  1324. *bpersec=0.0;
  1325.  
  1326. /* Determine the configuration of the hard disk */
  1327. if(get_hdinfo(drive+0x80,&myhdisk)==0)
  1328.     return;
  1329.  
  1330. /* Build the cylinder/sector and # of sectors arrays */
  1331. if(allocmem(n/4+1,&cysecarrseg)!=-1)
  1332.     return;
  1333. cysecptr=MK_FP(cysecarrseg,0);        /* Make a pointer */
  1334. if(allocmem((myhdisk.sectspertrack*512)/16+1,&buffseg)!=-1)
  1335. {    freemem(cysecarrseg);
  1336.     return;
  1337. }
  1338.  
  1339. /* Build arrays for first test */
  1340. randnum(1L);
  1341. i=0;
  1342. totbytes=0L;
  1343. do {
  1344.     cyl=abs((int)randwc((unsigned long)myhdisk.maxcyl));
  1345.     sect=abs((int)randwc((unsigned long)myhdisk.sectspertrack))+1;
  1346.     *(cysecptr+i)=(sect&0x3f)+((cyl&255)<<8)+((cyl&0x300)>>2);
  1347.     ++i;
  1348.     *(cysecptr+i)=myhdisk.sectspertrack-sect+1;
  1349.     totbytes+=(unsigned long)*(cysecptr+i);
  1350. } while(++i<((n*2)-1));
  1351.  
  1352. totbytes=(totbytes-(unsigned long)n)*512L;    /* FIX!!! */
  1353.  
  1354. /* Do first test */
  1355. seektime1[0]=seektime1[1]=seektime1[2]=0;
  1356. start_timer();
  1357. i=hd_rread(drive+0x80,cysecarrseg,buffseg,n);
  1358. stop_timer(eltime);
  1359. if(i!=0) printf("Whoops at %d\n",i);
  1360. accumtime(eltime,seektime1);
  1361.  
  1362. /* Fix up array for second test */
  1363. for(i=0;i<n;i++)
  1364.     *(cysecptr+2*i+1)=1;
  1365.  
  1366. /* Do second test */
  1367. seektime2[0]=seektime2[1]=seektime2[2]=0;
  1368. start_timer();
  1369. i=hd_rread(drive+0x80,cysecarrseg,buffseg,n);
  1370. stop_timer(eltime);
  1371. if(i!=0) printf("2Whoops at %d\n",i);
  1372. accumtime(eltime,seektime2);
  1373.  
  1374. /* Calculate bytes per second */
  1375. *bpersec=(double)totbytes/(timetodouble(seektime1)-timetodouble(seektime2));
  1376.  
  1377. /* Close it up */
  1378. freemem(cysecarrseg);
  1379. freemem(buffseg);
  1380.  
  1381. return;
  1382. }
  1383.  
  1384. /****************************
  1385. *     get_hdinfo            *
  1386. *****************************
  1387. ** Return hard disk information.
  1388. ** Call with:
  1389. **    drive = hard disk number (0x80 is first drive, 0x81 is second)
  1390. ** Returns:
  1391. **    hdinf structure filled with disk information
  1392. **    return value is number of drives connected to first
  1393. **       controller
  1394. */
  1395. int get_hdinfo(drive,hdinf)
  1396. unsigned int drive;    /* Drive to get information on */
  1397. harddiskspecs *hdinf;    /* Structure of hard disk info */
  1398. {
  1399.  
  1400. union REGS inregs, outregs;    /* For talking to the BIOS */
  1401.  
  1402. /* Make the call to INT 13H */
  1403. inregs.h.ah=8;
  1404. inregs.h.dl=drive;
  1405. int86(0x13,&inregs,&outregs);
  1406.  
  1407. /* Pass back results */
  1408. hdinf->maxhead=outregs.h.dh;
  1409. hdinf->maxcyl=outregs.h.ch + ((outregs.h.cl & 0xC0)<<2);
  1410. hdinf->sectspertrack=outregs.h.cl & 0x3F;
  1411.  
  1412. /* Return number of attached drives */
  1413. return((int)outregs.h.dl);
  1414. }
  1415.  
  1416. /****************************
  1417. *     segcopy              *
  1418. *****************************
  1419. * Given two segments, copies n bytes from source to
  1420. * destination.
  1421. */
  1422. segcopy(destin,source,n)
  1423. unsigned int destin;        /* Destination segment */
  1424. unsigned int source;        /* Source segment */
  1425. unsigned int n;        /* Number of bytes */
  1426. {
  1427. char huge *dptr;
  1428. char huge *sptr;
  1429.  
  1430. /* Make some far pointers */
  1431. dptr=MK_FP(destin,0);
  1432. sptr=MK_FP(source,0);
  1433.  
  1434. do {
  1435.     *dptr++=*sptr++;
  1436. } while(--n);
  1437.  
  1438. }
  1439.  
  1440. /****************************
  1441. *     rload_int_seg         *
  1442. *****************************
  1443. ** Load a segment with random integers.
  1444. ** Call with:
  1445. **   rload_int_seg(segptr,n,max)
  1446. ** Where:
  1447. **   segptr = unsigned integer holding the segment
  1448. **   n = number of elements to load the array
  1449. **   max = maximum value (must be unsigned)
  1450. */
  1451. rload_int_seg(segptr,n,max)
  1452. unsigned int segptr;
  1453. unsigned int n;
  1454. int max;
  1455. {
  1456. int huge *mysegptr;    /* For coercion */
  1457. unsigned int i;        /* Index */
  1458.  
  1459. /* Set up my pointer */
  1460. mysegptr=MK_FP(segptr,0);
  1461.  
  1462. /* Loop and load the array */
  1463. for(i=0;i<n;i++)
  1464.     *mysegptr++=(int)randwc((long)max);
  1465. }
  1466.  
  1467. /****************************
  1468. *      accumtime()          *
  1469. *****************************
  1470. ** Accumulate elapsed time.
  1471. ** Call with:
  1472. **   accumtime(eltime,tottime)
  1473. ** Where:
  1474. **   eltime[3] = array of elapsed time to be added to
  1475. **               tottime
  1476. ** Returns:
  1477. **   tottime[3] = total time
  1478. */
  1479. accumtime(eltime,tottime)
  1480. unsigned int eltime[3];        /* Elapsed time */
  1481. unsigned int tottime[3];    /* Total time */
  1482. {
  1483.  
  1484. /* Add in microseconds */
  1485. tottime[0]+=eltime[0];
  1486.  
  1487. /* Handle overflow */
  1488. while(tottime[0]>=1000)
  1489. {    tottime[0]-=1000;
  1490.     tottime[1]+=1;
  1491. }
  1492.  
  1493. /* Add in milliseconds */
  1494. tottime[1]+=eltime[1];
  1495.  
  1496. /* Handle overflow */
  1497. while(tottime[1]>=1000)
  1498. {    tottime[1]-=1000;
  1499.     tottime[2]+=1;
  1500. }
  1501.  
  1502. /* Add in seconds */
  1503. tottime[2]+=eltime[2];
  1504. }
  1505.  
  1506. /****************************
  1507. *         randwc()          *
  1508. *****************************
  1509. ** Returns random modulo num.
  1510. */
  1511. long randwc(num)
  1512. long num;
  1513. {
  1514.     return(randnum(0L)%num);
  1515. }
  1516.  
  1517. /****************************
  1518. *        randnum()          *
  1519. *****************************
  1520. ** Second order linear congruential generator.
  1521. ** Constants suggested by J. G. Skellam.
  1522. ** If val==0, returns next member of sequence.
  1523. **    val!=0, restart generator.
  1524. */
  1525. long randnum(lngval)
  1526. long lngval;
  1527. {
  1528.     register long interm;
  1529.     static long randw[2] = { 13L , 117L };
  1530.  
  1531.     if (lngval!=0L)
  1532.     {    randw[0]=13L; randw[1]=117L; }
  1533.  
  1534.     interm=(randw[0]*254754L+randw[1]*529562L)%999563L;
  1535.     randw[1]=randw[0];
  1536.     randw[0]=interm;
  1537.     return(interm);
  1538. }
  1539.  
  1540. /****************************
  1541. *     timetodouble          *
  1542. *****************************
  1543. * Convert a time array micro, milli, seconds to a floating-point
  1544. * double value.
  1545. */
  1546. double timetodouble(histime)
  1547. unsigned int histime[3];
  1548. {
  1549. double temp;        /* Local for holding time */
  1550.  
  1551.     temp=(double)histime[0];    /* Microseconds */
  1552.     temp=temp/1000.0;
  1553.     temp+=(double)histime[1];    /* Milliseconds */
  1554.     temp=temp/1000.0;
  1555.     temp+=(double)histime[2];    /* Seconds */
  1556.  
  1557.     return(temp);
  1558. }
  1559.  
  1560. void adjust_bar(win_handle *winptr, int curr, int tot)
  1561. /****************************
  1562. **      adjust_bar          *
  1563. *****************************
  1564. **
  1565. **
  1566. ** Colors the sliding bar graph
  1567. */
  1568. {
  1569. double curlen;
  1570. int i;
  1571.  
  1572.     curlen = ((double)curr/tot)*20;
  1573.  
  1574.     curlen=(curlen>20) ? 20: curlen;
  1575.  
  1576.     for(i=oldlen;i< (int) curlen;i++){
  1577.         winputch(winptr, 39+i, 23, 0xb2);
  1578.         if (tdef[13])
  1579.             click();
  1580.         }
  1581.  
  1582.     chattr(winptr, 39, 23, (int) curlen, 1, WHITE, RED);
  1583.  
  1584.     oldlen=curlen;
  1585.     return;
  1586. }
  1587.